/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "json_implement.h"
#include "yyjson.h"
#include "json_error.h"
#include "yyjson_util.h"

using namespace json_error;
using namespace yyjson_util;

napi_value json_implement::ParseJson(napi_env env, const char *jsonStr, size_t len) {
    unique_yyjson_doc doc(yyjson_read(jsonStr, len, YYJSON_READ_INSITU));
    if (doc.get() == nullptr) {
        handleYYJSONError(env, YYJSON_CREATE_DOC_FAILED);
    }
    yyjson_val *root = yyjson_doc_get_root(doc.get());
    return yyjson_to_napi(env, root);
}

napi_value json_implement::ParseInc(napi_env env, char *data, size_t byteLength) {
    unique_yyjson_incr_state state(yyjson_incr_new(data, byteLength, YYJSON_READ_INSITU, NULL));
    if (state.get() == nullptr) {
        handleYYJSONError(env, YYJSON_CREATE_DOC_FAILED);
    }
    
    unique_yyjson_doc doc;
    yyjson_read_err err;
    size_t readSoFar = 0;
    const size_t BLOCK_SIZE = 102400;
    do {
        readSoFar += BLOCK_SIZE;
        if (readSoFar > byteLength) {
            readSoFar = byteLength;
        }
        doc.reset(yyjson_incr_read(state.get(), readSoFar, &err));
        if (err.code != YYJSON_READ_SUCCESS) {
            handleYYJSONError(env, err.code);
        }
    } while (readSoFar < byteLength);
    
    if (doc.get() == nullptr) {
        handleYYJSONError(env, YYJSON_CREATE_DOC_FAILED);
    }
    
    yyjson_val *root = yyjson_doc_get_root(doc.get());
    return yyjson_to_napi(env, root);
}

napi_value json_implement::Stringify(napi_env env, napi_value value) {
    unique_yyjson_mut_doc doc(yyjson_mut_doc_new(nullptr));
    
    yyjson_mut_val *root = napi_to_yyjson(env, doc.get(), value);
    yyjson_mut_doc_set_root(doc.get(), root);
    
    std::unique_ptr<char, FreeDeleter> json(yyjson_mut_write(doc.get(), YYJSON_WRITE_NOFLAG, nullptr));
    if (json.get() == nullptr) {
        handleYYJSONError(env, YYJSON_MUT_WRITE_ERROR);
    }
    
    napi_value result;
    handleNapiError(env, napi_create_string_utf8(env, json.get(), NAPI_AUTO_LENGTH, &result));
    return result;
}